package com.chuxing.system.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chuxing.config.GroupRole;
import com.chuxing.domain.ClassInfo;
import com.chuxing.domain.DTO.TGroupsListDTO;
import com.chuxing.domain.TClassMembers;
import com.chuxing.domain.TGroupMembers;
import com.chuxing.domain.TGroups;
import com.chuxing.domain.VO.PageResultVO;
import com.chuxing.exception.GenericException;
import com.chuxing.system.mapper.ClassinfoMapper;
import com.chuxing.system.mapper.TClassMembersMapper;
import com.chuxing.system.mapper.TGroupMembersMapper;
import com.chuxing.system.mapper.TGroupsMapper;
import com.chuxing.system.service.ITGroupsService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.List;

/**
 * 小组Service业务层处理
 * 
 * @author 刘祺
 * @date 2025-01-11
 */
@Service
@Transactional
@Slf4j
@RequiredArgsConstructor
public class TGroupsServiceImpl extends ServiceImpl<TGroupsMapper, TGroups> implements ITGroupsService
{
    private final TGroupsMapper tGroupsMapper;
    private final TGroupMembersMapper tGroupMembersMapper;
    private final TClassMembersMapper tClassMembersMapper;

    /**
     * 查询小组
     * 
     * @param groupID 小组主键
     * @return 小组
     */
    @Override
    public TGroups selectTGroupsByGroupID(Long groupID)
    {
        return tGroupsMapper.selectTGroupsByGroupID(groupID);
    }

    /**
     * 查询小组列表
     *
     * @return 小组
     */
    @Override
    @Cacheable(value = "tGroupsList", key = "#tGroupsListDTO")
    public PageResultVO selectTGroupsList(TGroupsListDTO tGroupsListDTO)
    {
        // 验证分页参数
        int pageNum = Math.max(1, tGroupsListDTO.getPageNum());
        int pageSize = Math.max(1, tGroupsListDTO.getPageSize());
        // 启用分页查询
        PageHelper.startPage(pageNum, pageSize);
        try {
            try (Page<TGroups> page = tGroupsMapper.selectTGroupsList(tGroupsListDTO)) {
                // 构造并返回分页结果对象
                return new PageResultVO(page.getTotal(), page.getResult());
            }
        } catch (Exception e) {
            // 抛出通用异常，不暴露具体错误信息
            throw new GenericException("系统内部错误");
        } finally {
            // 确保分页查询结束
            PageHelper.clearPage();
        }
    }

    /**
     * 新增小组
     *
     * @param tGroups 小组
     * @return 结果
     */
    @Override
    @CacheEvict(value = "tGroupsList", allEntries = true)
    public int insertTGroups(TGroups tGroups)
    {
        // 设置创建时间
        tGroups.setCreatedDate(LocalDate.now());
        return tGroupsMapper.insertTGroups(tGroups);
    }

    /**
     * 修改小组
     * 
     * @param tGroups 小组
     * @return 结果
     */
    @Override
    @Caching(evict = {
            @CacheEvict(value = "tGroupsList", allEntries = true),
            @CacheEvict(value = "tGroupMembersList", allEntries = true)
    })
    public int updateTGroups(TGroups tGroups)
    {
        TGroups tGroups1 = selectTGroupsByGroupID(tGroups.getGroupID());
        // 修改组长
        if(tGroups.getGroupLeaderID()!=null&&!tGroups.getGroupLeaderID().equals(tGroups1.getGroupLeaderID())){
            //修改对应的组员身份为组长
            tGroupMembersMapper.updateRoleInGroupBystudentID(tGroups.getGroupLeaderID(),tGroups.getGroupID(), GroupRole.GROUP_LEADER);
            //修改对应的原组长身份为组员
            tGroupMembersMapper.updateRoleInGroupBystudentID(tGroups1.getGroupLeaderID(),tGroups.getGroupID(),GroupRole.GROUP_MEMBER);
        }
        // 删除原组长
        if(tGroups.getGroupLeaderID()==null&&tGroups1.getGroupLeaderID()!=null){
            tGroupMembersMapper.updateRoleInGroupBystudentID(tGroups1.getGroupLeaderID(),tGroups.getGroupID(),GroupRole.GROUP_MEMBER);
        }
        return tGroupsMapper.updateTGroups(tGroups);
    }

    /**
     * 批量删除小组
     * 
     * @param groupIDs 需要删除的小组主键
     * @return 结果
     */
    @Override
    @CacheEvict(value = "tGroupsList", allEntries = true)
    public int deleteTGroupsByGroupIDs(Long[] groupIDs)
    {
        //如果该小组下有成员，则不能删除
        for (Long groupID : groupIDs) {
            if(tGroupMembersMapper.countByGroupID(groupID)>0){
                throw new GenericException("小组下有成员，无法删除");
            }
        }
        return tGroupsMapper.deleteTGroupsByGroupIDs(groupIDs);
    }

    /**
     * 选择用户所在小组的信息列表
     * 此方法首先获取当前登录用户的ID，然后根据用户ID查询该用户所属的所有小组信息
     * 如果用户不属于任何小组，则返回null；否则返回小组信息列表
     *
     * @return 用户所在小组的信息列表，如果用户未加入任何小组则返回null
     */
    @Override
    public List<TGroups> selectGroupsMessageList() {
        // 获取当前登录用户的ID
        String loginId = StpUtil.getLoginIdAsString();
        // 根据用户ID查询该用户所属的所有小组成员记录
        List<TGroupMembers> list=tGroupMembersMapper.selectTGroupIDByStudentId(loginId);
        // 将list中的groupID查询出对应的小组信息
        long[] groupIDs=list.stream().mapToLong(TGroupMembers::getGroupID).toArray();
        // 如果用户不属于任何小组，返回null
        if(groupIDs.length==0){
            return null;
        }
        // 根据小组ID数组查询并返回小组信息列表
        return tGroupsMapper.selectTGroupsByGroupIDs(groupIDs);
    }

    /**
     * 根据班级ID选择群组列表
     * 此方法用于获取特定班级的所有群组信息它首先创建了一个DTO对象来设置分页参数和班级ID，
     * 然后通过用户服务和班级信息映射器来获取必要的信息最后，调用另一个方法来获取群组列表
     *
     * @return 返回一个包含群组列表的PageResultVO对象
     */
    @Override
    @Cacheable(value = "tGroupsList", key = "'classInfo'+#classInfo")
    public PageResultVO selectTGroupsListByClassId(ClassInfo classInfo) {
        if(classInfo==null){
            throw new GenericException("暂未开启班级分组！");
        }
        TClassMembers tClassMembers = tClassMembersMapper.selectTclassMembersByStudentIdAndTClassInfo(StpUtil.getLoginIdAsString(), classInfo.getId());
        if(tClassMembers==null){
            throw new GenericException("未加入班级！");
        }
        // 创建TGroupsListDTO对象并初始化分页参数
        TGroupsListDTO tGroupsListDTO = new TGroupsListDTO();
        tGroupsListDTO.setPageNum(1);
        tGroupsListDTO.setPageSize(Integer.MAX_VALUE);
        tGroupsListDTO.setClassID(classInfo.getId());
        // 调用方法获取群组列表并返回
        return selectTGroupsList(tGroupsListDTO);
    }
}
